﻿using NUnit.Framework;
using Shouldly;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;

namespace Test.MySql.ColumnTypeTests
{
    [TestFixture]
    internal class ColumnTypesTestInts : TestBase
    {
        #region 模型
        [Table("test")]
        public class Model
        {
            /// <summary>
            /// column: tinyint
            /// </summary>
            public sbyte? t_tinyint { get; set; }
            /// <summary>
            /// column: smallint
            /// </summary>
            public short? t_smallint { get; set; }
            /// <summary>
            /// column: mediumint
            /// </summary>
            public int? t_mediumint { get; set; }
            /// <summary>
            /// column: int
            /// </summary>
            public int? t_int { get; set; }
            /// <summary>
            /// column: bigint
            /// </summary>
            public long? t_bigint { get; set; }

            /// <summary>
            /// column: tinyint unsigned
            /// </summary>
            public byte? t_tinyint_unsigned { get; set; }
            /// <summary>
            /// column: smallint unsigned
            /// </summary>
            public ushort? t_smallint_unsigned { get; set; }
            /// <summary>
            /// column: mediumint unsigned
            /// </summary>
            public uint? t_mediumint_unsigned { get; set; }
            /// <summary>
            /// column: int unsigned
            /// </summary>
            public uint? t_int_unsigned { get; set; }
            /// <summary>
            /// column: bigint unsigned
            /// </summary>
            public ulong? t_bigint_unsigned { get; set; }
        }
        #endregion

        [SetUp]
        public void Setup()
        {
            DropTableIfExist("test");
            db.ExecuteSql(@"
create table test(
	t_tinyint tinyint,
	t_smallint smallint,
	t_mediumint mediumint,
	t_int int,
	t_bigint bigint,
	
	t_tinyint_unsigned tinyint unsigned,
	t_smallint_unsigned smallint unsigned,
	t_mediumint_unsigned mediumint unsigned,
	t_int_unsigned int unsigned,
	t_bigint_unsigned bigint unsigned
)");
            db.ExecuteSql("""
                insert into test.test(t_tinyint,t_smallint,t_mediumint,t_int,t_bigint,t_tinyint_unsigned,t_smallint_unsigned,t_mediumint_unsigned,t_int_unsigned,t_bigint_unsigned)	
                values (1,2,3,4,5,1,2,3,4,5),(-1,-2,-3,-4,-5,1,2,3,4,5);
                """);
        }

        [Test]
        public void TestDefaultParse()
        {
            var list = db.SelectDictionaryList("select * from test");
            var dic = list[0];
            validate(dic);
            dic["t_tinyint"].ShouldBe(1);
            dic["t_smallint"].ShouldBe(2);
            dic["t_mediumint"].ShouldBe(3);
            dic["t_int"].ShouldBe(4);
            dic["t_bigint"].ShouldBe(5);

            dic["t_tinyint_unsigned"].ShouldBe(1);
            dic["t_smallint_unsigned"].ShouldBe(2);
            dic["t_mediumint_unsigned"].ShouldBe(3);
            dic["t_int_unsigned"].ShouldBe(4);
            dic["t_bigint_unsigned"].ShouldBe(5);

            dic = list[1];
            validate(dic);

            void validate(Dictionary<string, object> dic)
            {
                dic["t_tinyint"].GetType().ShouldBe(typeof(sbyte));
                dic["t_smallint"].GetType().ShouldBe(typeof(short));
                dic["t_mediumint"].GetType().ShouldBe(typeof(int));
                dic["t_int"].GetType().ShouldBe(typeof(int));
                dic["t_bigint"].GetType().ShouldBe(typeof(long));

                dic["t_tinyint_unsigned"].GetType().ShouldBe(typeof(byte));
                dic["t_smallint_unsigned"].GetType().ShouldBe(typeof(ushort));
                dic["t_mediumint_unsigned"].GetType().ShouldBe(typeof(uint));
                dic["t_int_unsigned"].GetType().ShouldBe(typeof(uint));
                dic["t_bigint_unsigned"].GetType().ShouldBe(typeof(ulong));
            }

        }

        [Test]
        public void TestOrmReadWrite()
        {
            var models = db.SelectModelList<Model>("select * from test");
            validate(models[0]);
            models[1].t_tinyint.Value.ShouldBe((sbyte)-1);

            var sql = db.Insert<Model>().SetEntity(models[0]).ToSql();
            sql.ShouldBe("insert into test(`t_tinyint`,`t_smallint`,`t_mediumint`,`t_int`,`t_bigint`,`t_tinyint_unsigned`,`t_smallint_unsigned`,`t_mediumint_unsigned`,`t_int_unsigned`,`t_bigint_unsigned`) values(1,2,3,4,5,1,2,3,4,5);");

            TruncateTable("test");
            db.Insert<Model>().SetEntity(models[0]).ExecuteAffrows();
            models = db.SelectModelList<Model>("select * from test");
            validate(models[0]);


            void validate(Model model)
            {
                model.t_tinyint.Value.ShouldBe((sbyte)1);
                model.t_smallint.ShouldBe((short)2);
                model.t_mediumint.ShouldBe(3);
                model.t_int.ShouldBe(4);
                model.t_bigint.ShouldBe(5L);

                model.t_tinyint_unsigned.Value.ShouldBe((byte)1);
                model.t_smallint_unsigned.ShouldBe((ushort)2);
                model.t_mediumint_unsigned.ShouldBe((uint)3);
                model.t_int_unsigned.ShouldBe((uint)4);
                model.t_bigint_unsigned.ShouldBe((ulong)5L);
            }
        }
    }
}
